#ifndef HEADER_fd_src_disco_pack_fd_pack_tip_prog_blacklist_h
#define HEADER_fd_src_disco_pack_fd_pack_tip_prog_blacklist_h

#include "../../ballet/txn/fd_txn.h" /* for fd_acct_addr_t */
#include "../../ballet/fd_ballet_base.h"

#define MAP_PERFECT_NAME        fd_pack_tip_prog_blacklist
#define MAP_PERFECT_LG_TBL_SZ   5
#define MAP_PERFECT_T           fd_acct_addr_t
#define MAP_PERFECT_HASH_C      240642447U
#define MAP_PERFECT_KEY         b
#define MAP_PERFECT_KEY_T       fd_acct_addr_t const *
#define MAP_PERFECT_ZERO_KEY    (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0)
#define MAP_PERFECT_COMPLEX_KEY 1
#define MAP_PERFECT_KEYS_EQUAL(k1,k2) (!memcmp( (k1), (k2), 32UL ))

#define PERFECT_HASH( u ) (((MAP_PERFECT_HASH_C*(u))>>27)&0x1FU)

#define MAP_PERFECT_HASH_PP( a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15, \
                             a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) \
                                          PERFECT_HASH( (a08 | (a09<<8) | (a10<<16) | (a11<<24)) )
#define MAP_PERFECT_HASH_R( ptr ) PERFECT_HASH( fd_uint_load_4( (uchar const *)ptr->b + 8UL ) )

/* Mainnet tip payment program */
#define _T1pyyaTNZsKv2WcRAB8oVnk93mLJw2XzjtVYqCsaHqt  0x06U,0xaaU,0x09U,0x54U,0x8bU,0x50U,0x47U,0x6aU,0xd4U,0x62U,0xf9U,0x1fU,0x89U,0xa3U,0x01U,0x50U, \
                                                      0x33U,0x26U,0x4fU,0xc9U,0xabU,0xd5U,0x27U,0x00U,0x20U,0xa9U,0xd1U,0x42U,0x33U,0x47U,0x42U,0xfbU
/* Testnet tip payment program */
#define _DCN82qDxJAQuSqHhv2BJuAgi41SPeKZB5ioBCTMNDrCC 0xb5U,0x35U,0x83U,0x8dU,0x16U,0x31U,0x39U,0x77U,0xe9U,0xbfU,0xddU,0xfcU,0xe2U,0x14U,0x57U,0x81U, \
                                                      0xf5U,0x24U,0x0bU,0x69U,0x71U,0x03U,0x6bU,0x3bU,0x9fU,0x62U,0x11U,0x07U,0x1dU,0x0dU,0x93U,0x1dU
/* Mainnet tip payment config account */
#define _HgzT81VF1xZ3FT9Eq1pHhea7Wcfq2bv4tWTP3VvJ8Y9D 0xf7U,0xf9U,0x9aU,0x09U,0x42U,0xfaU,0xc7U,0x88U,0x05U,0x49U,0x43U,0xabU,0xbcU,0xf9U,0x46U,0xb1U, \
                                                      0xf9U,0xb9U,0x16U,0xcbU,0xe1U,0x0aU,0xedU,0xcfU,0xa9U,0x96U,0x76U,0x65U,0x37U,0x1cU,0xa2U,0x80U
/* Testnet tip payment config account */
#define _AXaHLTKzVyRUccE8bPskqsnc1YcTd648PjmMwKWS7R6N 0x8dU,0x8eU,0x3dU,0x00U,0x46U,0x5aU,0x5cU,0xa3U,0x4eU,0x92U,0x0dU,0x79U,0x8eU,0xd8U,0x35U,0xecU, \
                                                      0x86U,0x45U,0x36U,0x7aU,0x12U,0x38U,0x74U,0x38U,0xb1U,0x6aU,0x85U,0x39U,0x80U,0x37U,0x2eU,0xb7U
/* Mainnet tip accounts 0-7 */
#define _96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5 0x78U,0x52U,0x1cU,0xb1U,0x79U,0xceU,0xbbU,0x85U,0x89U,0xb5U,0x56U,0xa2U,0xd5U,0xecU,0x94U,0xd2U, \
                                                      0x49U,0x86U,0x82U,0xfdU,0xf9U,0xbbU,0x2aU,0xf5U,0xadU,0x64U,0xe4U,0x91U,0xccU,0x41U,0x53U,0xdaU
#define _HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe 0xf1U,0x87U,0xecU,0x87U,0xd1U,0xf7U,0x45U,0xcbU,0x3aU,0x03U,0x38U,0x4aU,0x26U,0xa6U,0x9eU,0xdaU, \
                                                      0x0cU,0xa2U,0xd1U,0xaaU,0x0fU,0x41U,0xe4U,0x24U,0x16U,0x37U,0x7eU,0x91U,0xffU,0x5bU,0x5dU,0x31U
#define _Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY 0xb1U,0x4eU,0x0dU,0xe5U,0x5eU,0x9fU,0xbaU,0x86U,0x39U,0x6eU,0xbfU,0xd5U,0x48U,0xcfU,0xf8U,0xc9U, \
                                                      0x20U,0x11U,0xeaU,0xc7U,0xb7U,0x5bU,0xaaU,0x9bU,0x2dU,0x9cU,0x6aU,0x86U,0xf5U,0xa1U,0x71U,0x41U
#define _ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49 0x88U,0xf1U,0xffU,0xa3U,0xa2U,0xdfU,0xe6U,0x17U,0xbdU,0xc4U,0xe3U,0x57U,0x32U,0x51U,0xa3U,0x22U, \
                                                      0xe3U,0xfcU,0xaeU,0x81U,0xe5U,0xa4U,0x57U,0x39U,0x0eU,0x64U,0x75U,0x1cU,0x00U,0xa4U,0x65U,0xe2U
#define _DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh 0xbcU,0x2bU,0x57U,0x06U,0x5eU,0xf1U,0xddU,0x66U,0x54U,0x30U,0xbeU,0x60U,0x6bU,0xa6U,0x59U,0x6cU, \
                                                      0x02U,0x95U,0x30U,0x1bU,0xadU,0xefU,0x8bU,0x5aU,0xfcU,0x41U,0x01U,0x41U,0x50U,0xf4U,0x12U,0x74U
#define _ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt 0x89U,0x07U,0x7dU,0x55U,0xa5U,0xbbU,0x13U,0x30U,0x76U,0x3eU,0xb7U,0x67U,0xf5U,0x5eU,0xc0U,0x77U, \
                                                      0xb4U,0x1aU,0x0dU,0x07U,0x5fU,0x7dU,0xe1U,0xd7U,0x3fU,0xbaU,0xcaU,0x3cU,0x63U,0xd5U,0x54U,0x71U
#define _DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL 0xbfU,0x97U,0x1bU,0x59U,0x10U,0x8bU,0x5bU,0x85U,0xa0U,0x4fU,0xb0U,0x93U,0xf1U,0xe2U,0x1bU,0x4eU, \
                                                      0x3fU,0xd4U,0xc4U,0xc8U,0xf4U,0x87U,0xddU,0x09U,0xb9U,0x57U,0x52U,0x76U,0x9fU,0x0dU,0xd8U,0xc3U
#define _3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT 0x20U,0x26U,0x10U,0x1eU,0xc2U,0x03U,0x28U,0x96U,0x4aU,0x32U,0xabU,0xabU,0x13U,0x6cU,0x54U,0x05U, \
                                                      0xb9U,0x1fU,0x3aU,0xe3U,0x8eU,0xe4U,0xf6U,0x4cU,0xb6U,0xbdU,0xe8U,0x79U,0xb8U,0x68U,0x38U,0xd2U

/* Testnet tip accounts 0-7 */
#define _BkMx5bRzQeP6tUZgzEs3xeDWJfQiLYvNDqSgmGZKYJDq 0x9fU,0xb0U,0x88U,0x29U,0xddU,0x15U,0xf4U,0x5dU,0x12U,0x90U,0x6fU,0xaeU,0x14U,0xe0U,0x98U,0x59U, \
                                                      0xc8U,0x5aU,0x08U,0x5aU,0xe5U,0xabU,0xddU,0x18U,0xd4U,0x06U,0x6eU,0xcbU,0xaeU,0x33U,0x59U,0x04U
#define _CwWZzvRgmxj9WLLhdoWUVrHZ1J8db3w2iptKuAitHqoC 0xb1U,0x67U,0x5aU,0x84U,0xd4U,0x5cU,0xc8U,0x0eU,0xe2U,0x8bU,0x61U,0xcbU,0x77U,0x00U,0x57U,0x75U, \
                                                      0xcbU,0xecU,0x91U,0xc3U,0xb2U,0x0dU,0x02U,0x7dU,0x22U,0x23U,0x45U,0x57U,0xcdU,0xf0U,0xa2U,0xc7U
#define _4uRnem4BfVpZBv7kShVxUYtcipscgZMSHi3B9CSL6gAA 0x3aU,0x01U,0x4aU,0x29U,0xbaU,0x3dU,0xc1U,0x18U,0x72U,0x58U,0x86U,0x66U,0x5bU,0xbcU,0xd4U,0xb1U, \
                                                      0x22U,0x11U,0x8bU,0x6dU,0x7aU,0xbbU,0x97U,0x68U,0x17U,0xd1U,0xabU,0x46U,0x4fU,0x0bU,0x84U,0xe7U
#define _AzfhMPcx3qjbvCK3UUy868qmc5L451W341cpFqdL3EBe 0x94U,0x7fU,0x0aU,0xb6U,0x0eU,0xc2U,0xb3U,0x78U,0xd7U,0xe5U,0x26U,0xfeU,0xc0U,0x0aU,0xe4U,0x83U, \
                                                      0x85U,0x6fU,0x7cU,0xfbU,0x80U,0x80U,0x9cU,0x93U,0x9dU,0xbbU,0xcfU,0x59U,0xf9U,0x55U,0x78U,0x3dU
#define _84DrGKhycCUGfLzw8hXsUYX9SnWdh2wW3ozsTPrC5xyg 0x68U,0xd5U,0x14U,0x6aU,0xceU,0x68U,0x5eU,0x90U,0x68U,0x46U,0xaeU,0xebU,0x49U,0x25U,0xfcU,0xe3U, \
                                                      0xedU,0xffU,0xd2U,0x69U,0x2cU,0x06U,0x03U,0xe5U,0x33U,0x2cU,0x02U,0x38U,0xfcU,0x39U,0x4aU,0x03U
#define _7aewvu8fMf1DK4fKoMXKfs3h3wpAQ7r7D8T1C71LmMF  0x01U,0xafU,0x89U,0xb0U,0x58U,0xdcU,0xafU,0x4dU,0x6dU,0x7aU,0xa0U,0x9cU,0xf9U,0x7cU,0xfdU,0xf3U, \
                                                      0xc1U,0x57U,0xf4U,0x4dU,0x89U,0x61U,0xcdU,0x63U,0x30U,0x20U,0xf2U,0x74U,0x00U,0x99U,0x1eU,0x3eU
#define _G2d63CEgKBdgtpYT2BuheYQ9HFuFCenuHLNyKVpqAuSD 0xdfU,0x49U,0xb0U,0x30U,0xe2U,0xa5U,0x16U,0x75U,0xfbU,0x82U,0xd4U,0x13U,0x7fU,0x96U,0x9aU,0x79U, \
                                                      0x8fU,0xc4U,0xa5U,0x91U,0xccU,0xdaU,0x47U,0x56U,0x16U,0x37U,0xa7U,0x60U,0x0eU,0xd6U,0xf9U,0xceU
#define _F7ThiQUBYiEcyaxpmMuUeACdoiSLKg4SZZ8JSfpFNwAf 0xd1U,0xabU,0x4bU,0x38U,0x6aU,0x2eU,0x14U,0x66U,0x41U,0x55U,0xedU,0xc4U,0xb8U,0xa1U,0x10U,0xdeU, \
                                                      0xfbU,0x01U,0x17U,0x53U,0x34U,0x51U,0xaeU,0x60U,0xb5U,0xdaU,0x02U,0xc2U,0x7eU,0xe8U,0xa7U,0x50U

/* This blacklist is really two different blacklists: one for
   transactions that come from bundles and another for transactions that
   don't come from bundles.  For bundles, we only prevent them from
   using the tip payment program.  That prevents an attack where someone
   submits a bundle that changes the tip receiver to themself, allowing
   them to steal the rest of the tips for the slot.  For non-bundles, we
   prevent the tip program for the same reason, but we also prevent
   access to the tip accounts and the config accounts, just to prevent
   potential contention.

   To implement this, the hash value is chosen specially.  The first two
   keys, the mainnet and testnet tip payment programs, respectively map
   to keys 1 and 0.  This means we can do a quick check: lookup each
   pubkey in the map.  If it comes from a bundle add the additional
   check that the index is <= 1 before throwing the transaction out. */
#define MAP_PERFECT_0  ( _T1pyyaTNZsKv2WcRAB8oVnk93mLJw2XzjtVYqCsaHqt  ),
#define MAP_PERFECT_1  ( _DCN82qDxJAQuSqHhv2BJuAgi41SPeKZB5ioBCTMNDrCC ),
#define MAP_PERFECT_2  ( _HgzT81VF1xZ3FT9Eq1pHhea7Wcfq2bv4tWTP3VvJ8Y9D ),
#define MAP_PERFECT_3  ( _AXaHLTKzVyRUccE8bPskqsnc1YcTd648PjmMwKWS7R6N ),
#define MAP_PERFECT_4  ( _96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5 ),
#define MAP_PERFECT_5  ( _HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe ),
#define MAP_PERFECT_6  ( _Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY ),
#define MAP_PERFECT_7  ( _ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49 ),
#define MAP_PERFECT_8  ( _DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh ),
#define MAP_PERFECT_9  ( _ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt ),
#define MAP_PERFECT_10 ( _DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL ),
#define MAP_PERFECT_11 ( _3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT ),
#define MAP_PERFECT_12 ( _BkMx5bRzQeP6tUZgzEs3xeDWJfQiLYvNDqSgmGZKYJDq ),
#define MAP_PERFECT_13 ( _CwWZzvRgmxj9WLLhdoWUVrHZ1J8db3w2iptKuAitHqoC ),
#define MAP_PERFECT_14 ( _4uRnem4BfVpZBv7kShVxUYtcipscgZMSHi3B9CSL6gAA ),
#define MAP_PERFECT_15 ( _AzfhMPcx3qjbvCK3UUy868qmc5L451W341cpFqdL3EBe ),
#define MAP_PERFECT_16 ( _84DrGKhycCUGfLzw8hXsUYX9SnWdh2wW3ozsTPrC5xyg ),
#define MAP_PERFECT_17 ( _7aewvu8fMf1DK4fKoMXKfs3h3wpAQ7r7D8T1C71LmMF  ),
#define MAP_PERFECT_18 ( _G2d63CEgKBdgtpYT2BuheYQ9HFuFCenuHLNyKVpqAuSD ),
#define MAP_PERFECT_19 ( _F7ThiQUBYiEcyaxpmMuUeACdoiSLKg4SZZ8JSfpFNwAf ),

#include "../../util/tmpl/fd_map_perfect.c"
#undef PERFECT_HASH

/* fd_pack_tip_prog_check_blacklist checks if a transaction that uses the
   specified account address should be allowed to execute, assuming
   Firedancer is configured to use a bundle engine.  acct points to the
   specified account address, which has no particular alignment
   constraint.  Returns a value in {0, 1, 3} with the following meaning:
    0: the specified account is allowed in any transaction
    1: the specified account is forbidden for non-bundle transactions
       but allowed for bundle transactions.
    3: the specified account is forbidden for both bundle and non-bundle
       transactions.
    (the value 2 is unused but reserved in for accounts that are
    forbidden in bundle transaction but allowed in non-bundle
    transactions.  You can maybe make an argument to include consensus
    accounts in this group, but I don't see a need to)

   The return values are chosen to facilitate aggregation using bitwise
   or. */
static inline int
fd_pack_tip_prog_check_blacklist( fd_acct_addr_t const * acct ) {
  uint hash = fd_pack_tip_prog_blacklist_hash_or_default( acct );
  return (hash!=UINT_MAX) + 2*(hash<=1U);
  /* GCC inserts a branch in the more readable version:
     return fd_int_if( hash==UINT_MAX, 0, fd_int_if( hash<=1U, 3, 1 ) );
   */
}

/* fd_pack_tip_is_tip_account checks if an account address is a a tip
   account or not.  If it is, it returns 1, otherwise it returns 0.  The
   hash of the tip program accounts map to <=1 and the config accounts
   map to >=30. */

static inline int
fd_pack_tip_is_tip_account( fd_acct_addr_t const * acct ) {
  uint hash = fd_pack_tip_prog_blacklist_hash_or_default( acct );
  return (hash!=UINT_MAX) && (hash>1U) && (hash<30U);
}

#undef  _T1pyyaTNZsKv2WcRAB8oVnk93mLJw2XzjtVYqCsaHqt
#undef  _DCN82qDxJAQuSqHhv2BJuAgi41SPeKZB5ioBCTMNDrCC
#undef  _HgzT81VF1xZ3FT9Eq1pHhea7Wcfq2bv4tWTP3VvJ8Y9D
#undef  _AXaHLTKzVyRUccE8bPskqsnc1YcTd648PjmMwKWS7R6N
#undef  _96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5
#undef  _HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe
#undef  _Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY
#undef  _ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49
#undef  _DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh
#undef  _ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt
#undef  _DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL
#undef  _3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT
#undef  _BkMx5bRzQeP6tUZgzEs3xeDWJfQiLYvNDqSgmGZKYJDq
#undef  _CwWZzvRgmxj9WLLhdoWUVrHZ1J8db3w2iptKuAitHqoC
#undef  _4uRnem4BfVpZBv7kShVxUYtcipscgZMSHi3B9CSL6gAA
#undef  _AzfhMPcx3qjbvCK3UUy868qmc5L451W341cpFqdL3EBe
#undef  _84DrGKhycCUGfLzw8hXsUYX9SnWdh2wW3ozsTPrC5xyg
#undef  _7aewvu8fMf1DK4fKoMXKfs3h3wpAQ7r7D8T1C71LmMF
#undef  _G2d63CEgKBdgtpYT2BuheYQ9HFuFCenuHLNyKVpqAuSD
#undef  _F7ThiQUBYiEcyaxpmMuUeACdoiSLKg4SZZ8JSfpFNwAf

#endif /* HEADER_fd_src_disco_pack_fd_pack_tip_prog_blacklist_h */
